package com.itealabs.shao.core;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;

/**
 * 
 * @author itea
 * 2009-12-19
 * $Id: ModuleManagerClassLoader.java 70 2009-12-30 09:54:45Z iteahere $
 */
public class ModuleManagerClassLoader extends ClassLoader implements ModuleManager {

	protected LinkedHashSet<Module> modules = new LinkedHashSet<Module>();

	public ModuleManagerClassLoader() {
		super();
	}

	public ModuleManagerClassLoader(ClassLoader parent) {
		super(parent);
	}

	/**
	 * Create a new ModuleManagerClassLoader instance and bind it to currentThread as the context ClassLoader.
	 * The original context ClassLoader would be the parent of the new ModuleManagerClassLoader instance.
	 * @return the new ModuleManagerClassLoader instance
	 */
	public static ModuleManager bind2currentTherad() {
	synchronized(ModuleManagerClassLoader.class) {
		ModuleManager mm = new ModuleManagerClassLoader(Thread.currentThread().getContextClassLoader());
		Thread.currentThread().setContextClassLoader(mm.getClassLoader());
		return mm;
	}
	}
	
	@Override
	public synchronized Module linkJar(File jar) throws IOException {
		Module m = new JarModuleClassLoader(jar, this);
		modules.add(m);
		return m;
	}

	@Override
	public synchronized boolean unlink(Module module) {
		if(modules.remove(module)) {
			module.unlink();
			return true;
		} else
			return false;
	}

	@Override
	public List<Module> getModules() {
		return new ArrayList<Module>(modules);
	}

	@Override
	public Module getModule(File jar) {
		for(Module m : modules)
			if(m.getJar().equals(jar))
				return m;
		return null;
	}

	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		for(Module m:modules)
			if(m.containsClass(name))
				return m.getClassLoader().loadClass(name);
		throw new ClassNotFoundException(name);
	}

	@Override
	protected URL findResource(String name) {
		for(Module m:modules)
			if(m.containsResource(name))
				return m.getClassLoader().getResource(name);
		return null;
	}

	@Override
	protected Enumeration<URL> findResources(String name) throws IOException {
		final ArrayList<URL> rs = new ArrayList<URL>();
		for(Module m:modules)
			if(m.containsResource(name))
				rs.add(m.getClassLoader().getResource(name));
		return new Enumeration<URL>() {
			Iterator<URL> rr = rs.iterator();
			@Override
			public boolean hasMoreElements() {
				return rr.hasNext();
			}

			@Override
			public URL nextElement() {
				return rr.next();
			}
			
		};
	}

	@Override
	public ClassLoader getClassLoader() {
		return this;
	}
}
